/*
 * Copyright 2012 Marsrutai.lt
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package lt.marsrutai.mobile.android.task;

import lt.marsrutai.mobile.android.activity.intent.TaskIntentHolder;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v4.app.Fragment;

/**
 * {@link AsyncTask} which notifies it's handler about state changes and job completion.
 * 
 * @author Justas
 * 
 * @param <Params>
 * @param <Progress>
 * @param <Result>
 * @see AsynTaskHandler
 */
public abstract class NotifyingAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {

    public static final int RESULT_NOT_RESOLVED = 10;
    
    /** Object which handles async task results and various state changes */
    private AsynTaskHandler<Progress> handler;
    /** task status */
    private int status = Activity.RESULT_OK;

    public void setCallback(AsynTaskHandler<Progress> callback) {
        this.handler = callback;
    }

    @Override
    protected void onProgressUpdate(Progress... progress) {
        if (handler == null) {
            return;
        }
        handler.onProgressUpdate(progress);
    }

    @Override
    protected void onPostExecute(Result result) {
        if (handler == null) {
            return;
        }
        handler.onFinished(getResultIntent(result));
    }
    
    @Override
    protected void onCancelled(Result result) {
        setResultStatus(Activity.RESULT_CANCELED);
        
        if (handler == null) {
            return;
        }
        handler.onCancelled(getResultIntent(result));
    }

    /**
     * Builds an intent object with computation results contained in the extras.
     * This is passed to {@link Fragment#onActivityResult(int, int, Intent)}.
     * 
     * @param result
     * @return
     */
    protected Intent getResultIntent(Result result) {
        TaskIntentHolder intentHolder = new TaskIntentHolder(getBroadcastAction());
        intentHolder.setStatus(getResultStatus());
        
        return intentHolder.getIntent();
    }
    
    protected abstract String getBroadcastAction();

    public int getResultStatus() {
        return status;
    }

    public void setResultStatus(int status) {
        this.status = status;
    }

    /**
     * Interface for callbacks
     * 
     * @author Justas
     *
     * @param <Progress>
     */
    public static interface AsynTaskHandler<Progress> {
        
        /**
         * Called when the task wants to update it's progress
         * 
         * @param progress
         */
        void onProgressUpdate(Progress... progress);
        
        /**
         * Called when the task is cancelled
         * 
         * @param resultIntent
         */
        void onCancelled(Intent resultIntent);

        /**
         * Called when the task is finished
         * 
         * @param result See {@link NotifyingAsyncTask#getResultIntent(Object)}
         */
        void onFinished(Intent result);
    }
}
